﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using EnvDTE;
using VSLangProj;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using Microsoft.VisualStudio.Shell.Design;
using System.ComponentModel.Design;

namespace Sharp.UnusedReferences
{
	class Helper
	{
		public delegate void ProcessHierarchyNode(IVsHierarchy hierarchy, uint itemid, int recursionLevel);

		/// <summary>
		/// This functions prints on the debug ouput and on the generic pane of the output window
		/// a text.
		/// </summary>
		/// <param name="text">text to send to Output Window.</param>
		private static void OutputCommandString(string text)
		{
			// Build the string to write on the debugger and output window.
			StringBuilder outputText = new StringBuilder(text);
			outputText.Append("\n");

			// Now print the string on the output window.
			// The first step is to get a reference to IVsOutputWindow.
			IVsOutputWindow outputWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow;

			// If we fail to get it we can exit now.
			if(null == outputWindow)
			{
				Trace.WriteLine("Failed to get a reference to IVsOutputWindow");
				return;
			}

			// Now get the window pane for the general output.
			Guid guidGeneral = Microsoft.VisualStudio.VSConstants.GUID_OutWindowGeneralPane;
			IVsOutputWindowPane windowPane;

			// following instructions on MEF Output Window forum. if this doesn't work, use the commented out stuff below this
			if(Microsoft.VisualStudio.ErrorHandler.Failed(outputWindow.GetPane(ref guidGeneral, out windowPane)) && (Microsoft.VisualStudio.ErrorHandler.Succeeded(outputWindow.CreatePane(ref guidGeneral, null, 1, 1))))
			{
				outputWindow.GetPane(ref guidGeneral, out windowPane);
			}
			//if (Microsoft.VisualStudio.ErrorHandler.Failed(outputWindow.GetPane(ref guidGeneral, out windowPane)))
			//{
			//    Trace.WriteLine("Failed to get a reference to the Output Window General pane");
			//    return;
			//}

			// following instructions on MEF Output Window forum. if this doesn't work, use the commented out stuff below this
			if(windowPane != null)
			{
				Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowPane.Activate());
			}
			//if (Microsoft.VisualStudio.ErrorHandler.Failed(windowPane.OutputString(outputText.ToString())))
			//{
			//    Trace.WriteLine("Failed to write on the output window");
			//}
		}

		public static ImageList GetImageList(IntPtr intPtr)
		{
			HandleRef hImageList = new HandleRef(null, intPtr);

			// get count of original images
			int imageOffset = SafeNativeMethods.ImageList_GetImageCount(hImageList);

			// create a bitmap to hold the images
			Bitmap bitmap = new Bitmap(16 * imageOffset, 16);
			Graphics graphics = Graphics.FromImage(bitmap);

			// extract into bitmap
			IntPtr hDC = IntPtr.Zero;
			try
			{
				hDC = graphics.GetHdc();
				HandleRef handleRefDC = new HandleRef(null, hDC);
				for(int i = 0; i < imageOffset; i++)
				{
					SafeNativeMethods.ImageList_Draw(hImageList, i, handleRefDC, i * 16, 0, 0 /*ILD_NORMAL*/);
				}
			}
			finally
			{
				if(graphics != null && hDC != IntPtr.Zero)
				{
					graphics.ReleaseHdc(hDC);
				}
			}

			// initialize new imagelist with images from base project hierarchy
			ImageList imageList = new ImageList();
			imageList.ColorDepth = ColorDepth.Depth24Bit;
			imageList.ImageSize = new Size(16, 16);
			imageList.Images.AddStrip(bitmap);
			//bitmap.Dispose();
			return imageList;
		}
	
		public static Dictionary<string, Type> GetAvailableTypes(IVsHierarchyWrapper hier, bool ExcludeGlobalTypes)
		{
			return GetAvailableTypes(hier.Hierarchy, ExcludeGlobalTypes);
		}
		public static Dictionary<string, Type> GetAvailableTypes(IVsHierarchy hier, bool ExcludeGlobalTypes)
		{
			Dictionary<string, Type> Result = new Dictionary<string, Type>();
			DynamicTypeService typeService = (DynamicTypeService)ServiceProvider.GlobalProvider.GetService(typeof(DynamicTypeService));
			if(typeService != null)
			{
				//IVsHierarchy hier = VsHelper.GetCurrentHierarchy(provider);
				ITypeDiscoveryService discovery = typeService.GetTypeDiscoveryService(hier);
				//Project dteProject = VsHelper.ToDteProject(hier);
				foreach(Type type in discovery.GetTypes(typeof(object), ExcludeGlobalTypes))
				{
					if(!Result.ContainsKey(type.FullName))
					{
						Result.Add(type.FullName, type);
					}
				}
			}
			return Result;
		}

		public static string ConvertToAbsolute(string BaseUri, string RelativeUri)
		{
			Uri UriAbsolute1 = new Uri(BaseUri);
			Uri UriRelative2 = new Uri(UriAbsolute1, RelativeUri);
			return UriRelative2.AbsolutePath;
		}

		public static void EmitProperties(Properties PropertiesToBeEmitted)
		{
			foreach(EnvDTE.Property property in PropertiesToBeEmitted)
			{
				try
				{
					Trace.WriteLine(string.Format("{0}\t\t|\t\t{1}", property.Name, property.Value));
				}
				catch(Exception Ex)
				{
					Trace.WriteLine(string.Format("{0}\t\t|\t\t{1}", property.Name, Ex.Message));
				}
			}
		}

	}
}
